import RemoteDeviceModel from '../Distribute/remotedevicemodel';
import featureAbility from '@ohos.ability.featureAbility';
import { KvStoreModel } from '../Distribute/kvstoremodel';

const TAG: string = 'BT_Demo[Distribute]'

let kvStoreModel: KvStoreModel = new KvStoreModel();
let remoteDeviceModel = new RemoteDeviceModel()
let timerId = 0

class Distribute {
    isDistributed = false
    onMessageReceivedListener: (s:string) => void = null
    onConnectionFinished: (boolean)=> void
    messageShow: (text: string) =>void
    bundleName: string
    abilityName: string
    appName: string

    init(onMessageReceivedListener: (s:string) => void,
         onConnectionFinished: (boolean)=> void,
         messageShow: (text: string) =>void,
         bundleName: string, abilityName: string, appName: string
    ) {
        this.onMessageReceivedListener = onMessageReceivedListener
        this.onConnectionFinished = onConnectionFinished
        this.messageShow = messageShow
        this.bundleName = bundleName
        this.abilityName = abilityName
        this.appName = appName
        console.log(`${TAG} init`);
        this.initKVManager();
    }

    grantPermission() {
        console.info(`${TAG} grantPermission`)
        let context = featureAbility.getContext()
        context.requestPermissionsFromUser(['ohos.permission.DISTRIBUTED_DATASYNC'], 666, function (result) {
            console.log(`${TAG} grantPermission,requestPermissionsFromUser,result.requestCode=${result}`)
        })
    }

    public stop() {
        this.isDistributed = false;
        if (remoteDeviceModel === undefined) {
            return
        }
        remoteDeviceModel.unregisterDeviceListCallback();
        if (this.isDistributed && kvStoreModel != null) {
            this.stopDataListener();
        }
        clearInterval(timerId)
        kvStoreModel = null
        remoteDeviceModel = undefined
    }

    initKVManager() {
        console.log(`${TAG} initKVManager start`);
        if (kvStoreModel == undefined || kvStoreModel == null) {
            console.log(`${TAG} kvStoreModel absent. create new kvStoreModel`);
            kvStoreModel = new KvStoreModel()
        }
        kvStoreModel.init(this.bundleName)
        kvStoreModel.setOnMessageReceivedListener('expression', (value) => {
            this.Listener(value)
        });
        console.log(`${TAG} initKVManager end`);
    }

    Listener(value) {
        if (this.onMessageReceivedListener != null) {
            //console.log(`${TAG} data input:` + value);
            this.onMessageReceivedListener(value)
        }
        else {
            console.log(`${TAG} data changed:` + value + ' no callback');
        }
    }

    stopDataListener() {
        console.log(`${TAG} stopDataListener`);
        if (kvStoreModel === null || kvStoreModel === undefined) {
            return
        }
        kvStoreModel.off()
    }
    // *****************************************************************************************************************
    connect() {
        let deviceList = []
        console.info(`${TAG} connect start`);
        if (this.isDistributed) {
            this.messageShow(`Connection is already completed`)
            this.ConnectionFinished(this.isDistributed)
            return
        }
        setTimeout(()=>{ // otherwise, the connection is not stable
            if (remoteDeviceModel === undefined) {
                remoteDeviceModel = new RemoteDeviceModel()
            }
            console.log(`${TAG} registerDeviceListCallback on remote device updated, count=`
            + remoteDeviceModel.deviceList.length);
            remoteDeviceModel.registerDeviceListCallback(this.bundleName, (err: string) => {
                if (err !== null) {
                    console.log(`${TAG} registerDeviceListCallback Error ${err}`)
                    this.messageShow(err)
                    this.ConnectionFinished(false)
                    return
                }
                deviceList = remoteDeviceModel.discoverList.length > 0 ? remoteDeviceModel.discoverList : remoteDeviceModel.deviceList;
                for (let i = 0; i < deviceList.length; i++) {
                    console.log(`${TAG} Device[${i}] ${deviceList[i].deviceName}`)
                }
            });
            setTimeout(()=>{ // otherwise NO DEVICES FOUND always
                if (deviceList.length > 0) {
                    console.log(`${TAG} Connecting to ${deviceList[0].deviceName}`)
                    this.messageShow(`Connecting to ${deviceList[0].deviceName}`)
                    this.connectToDevice(deviceList[0])
                }
                else {
                    console.log(`${TAG} NO DEVICES FOUND`)
                    this.messageShow('NO DEVICES FOUND')
                    this.cancelConnect()
                    this.ConnectionFinished(false)
                }
            },200)
        },200)
    }

    cancelConnect() {
        if (remoteDeviceModel === undefined) {
            return;
        }
        remoteDeviceModel.unregisterDeviceListCallback();
    }

    connectToDevice(item) {
        console.log(`${TAG} connectToDevice ` + JSON.stringify(item));
        if (remoteDeviceModel === undefined || remoteDeviceModel.discoverList.length <= 0) {
            console.log(`${TAG} start ability ......`);
            this.startAbility(item.deviceId);
            return;
        }
        console.log(`${TAG} start authentication`);
        remoteDeviceModel.authenticateDevice(item, this.bundleName, this.appName, (err: boolean) => {
            if (err) {
                this.messageShow('Authentication error')
                return
            }
            console.log(`${TAG} auth and online finished`);
            //this.ConnectionFinished(false)
            setTimeout(()=> {
                //this.startAbility(item.deviceId);
                this.messageShow('Please restart BT_Demo app')
                return
            }, 500)
        });
        console.log(`${TAG} start ability end....`);
    }

    dataTransmit(key, value) {
        //console.log(`${TAG} dataTransmit isDistributed = ` + this.isDistributed);
        if (this.isDistributed && kvStoreModel != null) {
            try{
                kvStoreModel.put(key, value);
            } catch(err) {
                console.error(`${TAG} dataTransmit error:` + err);
            }

        }
    }

    async startAbility(deviceId) {
        console.log(`${TAG} startAbility deviceId:` + deviceId);
        console.log(`${TAG} startAbility bundleName=${this.bundleName}`);
        console.log(`${TAG} startAbility abilityName=${`${this.bundleName}.${this.abilityName}`}`);
        if (deviceId === 0) {
            return
        }

        try {
            await featureAbility.startAbility({
                want: {
                    bundleName: this.bundleName,
                    abilityName: `${this.bundleName}.${this.abilityName}`,
                    deviceId: deviceId,
                    //parameters: {
                    //    isFA: 'FA' // isFA - value, 'FA' - key
                    //}
                }
            })
        } catch (err) {
            console.log(`${TAG} startAbility err is ${JSON.stringify(err)}`)
            this.messageShow(`StartAbility err is ${JSON.stringify(err)}`)
            this.ConnectionFinished(false)
            return
        }
        setTimeout(()=> {
            this.ConnectionFinished(true)
        }, 1000)
        console.log(`${TAG} startAbility end`);
    }

    ConnectionFinished(isDistributed: boolean) {
        console.info(`${TAG} conState ${this.isDistributed}->${isDistributed}`)
        this.isDistributed = isDistributed
        if (this.onConnectionFinished != null) {
            this.onConnectionFinished(isDistributed)
        }
    }
}

export let distribute = new Distribute